#ifndef CALCULATOR_H
#define CALCULATOR_H

#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <sstream>
#include <iomanip>
#include <cctype>
#include <stdexcept>
#include <cmath>

using namespace std;

class BigDecimal {
private:
    vector<int> digits;
    int decimalPlaces;
    bool isNegative;
    bool endPoint;
    bool input0;
    bool isresult;
    int numof0;
    static const int MAX_DECIMAL = 10;

    void normalize() {
        // 移除整数部分的前导零
        while (digits.size() > decimalPlaces + 1 && digits.back() == 0) {
            digits.pop_back();
        }

        // 移除小数部分的尾随零
        while (decimalPlaces > 0 && !digits.empty() && digits.front() == 0) {
            digits.erase(digits.begin());
            decimalPlaces--;
        }

        if (digits.empty()) {
            digits.push_back(0);
            decimalPlaces = 0;
            isNegative = false;
        }
    }

    void alignDecimals(BigDecimal& other) {
        int maxDecimal = max(decimalPlaces, other.decimalPlaces);
        ensureDecimalPlaces(maxDecimal);
        other.ensureDecimalPlaces(maxDecimal);
    }

    void ensureDecimalPlaces(int required) {
        while (decimalPlaces < required) {
            digits.insert(digits.begin(), 0);
            decimalPlaces++;
        }
    }

public:
    BigDecimal() : decimalPlaces(0), isNegative(false), endPoint(false), isresult(true), input0(false), numof0(0) {
        digits.push_back(0);
    }

    BigDecimal(const string& numStr,bool select = true) : decimalPlaces(0), isNegative(false), endPoint(false), input0(false), numof0(0) {
        string str = numStr;
        isresult = select;

        if(!isresult) {
            if(str[str.size()-1] == '0') {
                input0 = true;
                int j = 1;
                for(int i=2;str[str.size()-i] == '0';i++) {
                    numof0++;
                    j = i;
                }
                if(str[str.size()-j-1] == '.') {
                    endPoint = true;
                }
            }
        }

        if(str.find('.') == str.size()-1) {
            endPoint = true;
        }

        if (!str.empty() && str[0] == '-') {
            isNegative = true;
            str = str.substr(1);
        }

        str.erase(remove(str.begin(), str.end(), ','), str.end());

        size_t dotPos = str.find('.');
        string intPart, decPart;

        if (dotPos != string::npos) {
            intPart = str.substr(0, dotPos);
            decPart = str.substr(dotPos + 1);
            decimalPlaces = decPart.length();
        } else {
            intPart = str;
        }

        if (intPart.empty()) {
            digits.push_back(0);
        } else {
            for (int i = intPart.length() - 1; i >= 0; --i) {
                if (isdigit(intPart[i])) {
                    digits.push_back(intPart[i] - '0');
                }
            }
        }

        if (!decPart.empty()) {
            for (char c : decPart) {
                if (isdigit(c)) {
                    digits.insert(digits.begin(), c - '0');
                }
            }
        }

        normalize();
    }

    BigDecimal operator-() const {
        BigDecimal result = *this;
        if (!result.isZero()) {
            result.isNegative = !result.isNegative;
        }
        return result;
    }

    BigDecimal operator+(const BigDecimal& other) const {
        if (isNegative != other.isNegative) {
            if (isNegative) return other - (-(*this));
            else return *this - (-other);
        }

        BigDecimal a = *this, b = other;
        a.alignDecimals(b);

        BigDecimal result;
        result.digits.clear();
        result.decimalPlaces = a.decimalPlaces;

        int carry = 0;
        int maxLength = max(a.digits.size(), b.digits.size());
        for (int i = 0; i < maxLength || carry; ++i) {
            int sum = carry;
            if (i < a.digits.size()) sum += a.digits[i];
            if (i < b.digits.size()) sum += b.digits[i];

            result.digits.push_back(sum % 10);
            carry = sum / 10;
        }

        result.isNegative = isNegative;
        result.normalize();
        return result;
    }

    BigDecimal operator-(const BigDecimal& other) const {
        if (isNegative != other.isNegative) return *this + (-other);

        BigDecimal a = *this, b = other;
        a.alignDecimals(b);

        if (a.compareAbsolute(b) < 0) {
            BigDecimal result = b - a;
            result.isNegative = !isNegative;
            result.normalize();
            return result;
        }

        BigDecimal result;
        result.digits.clear();
        result.decimalPlaces = a.decimalPlaces;

        int borrow = 0;
        for (int i = 0; i < a.digits.size(); ++i) {
            int diff = a.digits[i] - borrow;
            if (i < b.digits.size()) diff -= b.digits[i];

            if (diff < 0) {
                diff += 10;
                borrow = 1;
            } else {
                borrow = 0;
            }

            result.digits.push_back(diff);
        }

        result.isNegative = isNegative;
        result.normalize();
        return result;
    }

    int compareAbsolute(const BigDecimal& other) const {
        BigDecimal a = *this, b = other;
        a.alignDecimals(b);

        if (a.digits.size() != b.digits.size()) {
            return a.digits.size() < b.digits.size() ? -1 : 1;
        }

        for (int i = a.digits.size() - 1; i >= 0; --i) {
            if (a.digits[i] != b.digits[i]) {
                return a.digits[i] < b.digits[i] ? -1 : 1;
            }
        }

        return 0;
    }

    bool isZero() const {
        for (int digit : digits) {
            if (digit != 0) return false;
        }
        return true;
    }

    string toString() const {
        string result;

        if (isNegative && !isZero()) {
            result += "-";
        }

        bool hasIntegerPart = false;
        for (int i = digits.size() - 1; i >= decimalPlaces; --i) {
            if (i < digits.size()) {
                result += to_string(digits[i]);
                hasIntegerPart = true;

                if (i > decimalPlaces && (i - decimalPlaces) % 3 == 0) {
                    result += ",";
                }
            }
        }

        if (!hasIntegerPart) {
            result += "0";
        }

        string decimalStr;
        bool hasDecimal = false;
        for (int i = decimalPlaces - 1; i >= 0; --i) {
            if (i < digits.size()) {
                decimalStr += to_string(digits[i]);
                if (digits[i] != 0) hasDecimal = true;
            }
        }

        if (hasDecimal) {
            while (!decimalStr.empty() && decimalStr.back() == '0') {
                decimalStr.pop_back();
            }
            if (!decimalStr.empty()) {
                result += "." + decimalStr;
            }
        }

        if(endPoint) {
            result += ".";
        }

        if(input0) {
            for(int i=0;i < numof0;i++) {
                result += "0";
            }
            result += "0";
        }

        return result;
    }
};

#endif // CALCULATOR_H
